<!--
 * @Author: xuhy 1727317079@qq.com
 * @Date: 2022-09-05 16:56:25
 * @LastEditors: xuhy 1727317079@qq.com
 * @LastEditTime: 2022-09-05 21:13:01
 * @FilePath: \vue3_test\05_Vue3的响应式原理\Vue3的响应式原理.html
 * @Description: 05_Vue3的响应式原理
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title></title>
  </head>
  <body>
    <script>
      // 源数据
      let person = {
        name: "张三",
        age: 18,
      };
      // 模拟Vue2中实现的响应式
      //#region
      /* let p = {};
      Object.defineProperty(p, "name", {
        configurable: true,
        // 有人读取name时调用
        get() {
          return person.name;
        },
        // 有人修改name时调用
        set(value) {
          console.log("有人修改了name属性, 我发现了, 我要去更新界面!");
          person.name = value;
        },
      });
      Object.defineProperty(p, "age", {
        configurable: true,
        // 有人读取name时调用
        get() {
          return person.age;
        },
        // 有人修改name时调用
        set(value) {
          console.log("有人修改了age属性, 我发现了, 我要去更新界面!");
          person.age = value;
        },
      }); */
      //#endregion

      // 模拟Vue3中实现的响应式
      // #region
      // Proxy的构造函数需要两个参数, 第一个参数是需要代理的源数据, 第二个参数可以采用空对象占位
      const p = new Proxy(person, {
        // 有人读取p的某个属性时调用
        get(target, propName) {
          console.log(`有人读取了p身上的${propName}属性`);
          return Reflect.get(target, propName);
        },
        // 有人修改p的某个属性, 或给p追加某个属性时调用
        set(target, propName, value) {
          console.log(`有人修改了p身上的${propName}属性, 我要去更新界面了!`);
          Reflect.set(target, propName, value);
        },
        // 有人删除p的某个属性时调用
        deleteProperty(target, propName) {
          console.log(`有人删除了p身上的${propName}属性, 我要去更新界面了!`);
          return Reflect.deleteProperty(target, propName);
        },
      });
      //#endregion

      let obj = { a: 1, b: 2 };
      // 通过Object.defineProperty去操作
      // #region
      /* try {
        Object.defineProperty(obj, "c", {
          get() {
            return 3;
          },
        });

        Object.defineProperty(obj, "c", {
          get() {
            return 4;
          },
        });
      } catch (error) {
        console.log(error);
      } */
      // #endregion

      // 通过Reflect去操作
      // #region
      /*  const x1 = Reflect.defineProperty(obj, "c", {
        get() {
          return 3;
        },
      });
      console.log(x1);

      const x2 = Reflect.defineProperty(obj, "c", {
        get() {
          return 4;
        },
      });

      if (x2) {
        console.log("操作成功了!");
      } else {
        console.log("操作失败了!");
      }
      console.log(x2); */
      // #endregion
    </script>
  </body>
</html>
